Imports AppliedRecognition.Speech.TaskSupport
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Runtime.Serialization
Imports System.Drawing
Imports System.Threading
Imports System.Globalization
Imports AppliedRecognition.Util
Imports System.Collections.Generic
Public Class ShowTasksForm
    Inherits QSBaseForm


    Private TS As New ARTraceSwitch("QS", "ShowTask Form")
    Friend WindowTasks As TaskSupport.TaskVisibleTasks

#Region " Windows Form Designer generated code "

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)

    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents TasksBP As BlendPanel
    Friend WithEvents NoSpeechDebugTimer As System.Windows.Forms.Timer
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Me.TasksBP = New AppliedRecognition.Speech.QuickSwitch.BlendPanel
        Me.NoSpeechDebugTimer = New System.Windows.Forms.Timer(Me.components)
        Me.SuspendLayout()
        '
        'TasksBP
        '
        Me.TasksBP.Blend = New AppliedRecognition.Speech.QuickSwitch.BlendFill(AppliedRecognition.Speech.QuickSwitch.BlendStyle.ForwardDiagonal, System.Drawing.SystemColors.InactiveCaption, System.Drawing.SystemColors.Window)
        Me.TasksBP.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
        Me.TasksBP.CausesValidation = False
        Me.TasksBP.Dock = System.Windows.Forms.DockStyle.Fill
        Me.TasksBP.Location = New System.Drawing.Point(0, 0)
        Me.TasksBP.Name = "TasksBP"
        Me.TasksBP.Size = New System.Drawing.Size(806, 450)
        Me.TasksBP.TabIndex = 0
        '
        'NoSpeechDebugTimer
        '
        '
        'ShowTasksForm
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.BackColor = System.Drawing.Color.FromArgb(CType(152, Byte), CType(112, Byte), CType(180, Byte))
        Me.ClientSize = New System.Drawing.Size(806, 450)
        Me.Controls.Add(Me.TasksBP)
        Me.Name = "ShowTasksForm"
        Me.ShowInTaskbar = False
        Me.Text = "Show Tasks"
        Me.ResumeLayout(False)

    End Sub

#End Region

#Region "Singlton"

    Private Shared _instance As ShowTasksForm = Nothing
    Private Shared _lock As Object = New Object

    '
    ' this Singleton is only used to ensure a single instance while the form is visible.
    ' that is to say it's not a memory management feature
    Public Shared ReadOnly Property Instance() As ShowTasksForm
        Get
            If _instance Is Nothing Then
                SyncLock _lock
                    If _instance Is Nothing Then
                        _instance = New ShowTasksForm
                        _instance.TS.WVerbose("New Instance")
                    End If
                End SyncLock
            End If
            Return _instance
        End Get
    End Property
    Private Sub Form_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
        _instance = Nothing
        TS.WVerbose("Closed")
    End Sub
    Public Shared ReadOnly Property Exists() As Boolean
        Get
            If _instance Is Nothing Then Return False
            Return True
        End Get
    End Property
#End Region

    Private Sub New()
        MyBase.New()
        InitializeComponent()
        TS.Level = My.MySettings.Default.QSTraceLevel
        HideFormTimer.Interval = My.MySettings.Default.DisplayTimout

    End Sub


#Region "   Debug Support"
#If DEBUG Then
    Private Sub NoSpeechDebugTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NoSpeechDebugTimer.Tick
        NoSpeechDebugTimer.Enabled = False
        ShowForm()
        Exit Sub
        For ii As Integer = 1 To 100000
            ShowForm()
            Application.DoEvents()
            Threading.Thread.Sleep(100)
            DoHide()
            Threading.Thread.Sleep(10)
            If ii Mod 100 = 0 Then
                TS.WInfo(ii.ToString(CultureInfo.CurrentCulture))
            End If
        Next
    End Sub
#End If

    Private Shared swItemCount As Integer
    Private Sub SerializeWindowItems()
        If Not My.MySettings.Default.DebugWindows Then Exit Sub

        Dim vs As New TaskSupport.VisibleTasks

        Dim dt As DateTime = Now
        Dim p As String = IO.Path.Combine(Dispatch.Cfg.DebugDataPath, "WindowDump" + swItemCount.ToString + ".dat")
        Dim fs As New IO.FileStream(p, IO.FileMode.Create)
        Dim bf As New BinaryFormatter

        vs.GetWindows()

        Try
            Dim swil As List(Of SerialiedWindowItem) = vs.GetSerialiedList(My.MySettings.Default.DebugWindowsCaptureScreenshot)
            bf.Serialize(fs, swil)
        Finally
            fs.Close()
        End Try

        p = IO.Path.Combine(Dispatch.Cfg.DebugDataPath, "TaskDump" + swItemCount.ToString + ".dat")
        fs = New IO.FileStream(p, IO.FileMode.Create)
        Dim tvt As New TaskSupport.TaskVisibleTasks(Me.Handle)
        tvt.GetWindows()
        bf.Serialize(fs, tvt.GetSerialiedList(My.MySettings.Default.DebugWindowsCaptureScreenshot))
        fs.Close()



        Dim xs As New Xml.Serialization.XmlSerializer(GetType(List(Of TaskSupport.SerialiedWindowItem)))
        p = IO.Path.Combine(Dispatch.Cfg.DebugDataPath, "WindowDump" + swItemCount.ToString + ".xml")
        fs = New IO.FileStream(p, IO.FileMode.Create)
        Try
            xs.Serialize(fs, vs.GetSerialiedList(My.MySettings.Default.DebugWindowsCaptureScreenshot))
        Finally
            fs.Close()

        End Try

        swItemCount += 1

    End Sub
#End Region

#Region "   Verbs"

    Protected Overrides Function ShowFormSetup() As Boolean
        TS.WVerbose("ShowTasks")

        SerializeWindowItems()
        WindowTasks = Dispatch.WindowTasks


        If WindowTasks.Items.Count < 2 Then
            TS.WVerbose("0 or 1 item, showing config")
            Dispatch.ShowConfigForm()
            Return False
        ElseIf WindowTasks.Items.Count = 2 Then
            TS.WVerbose("2 items, swapping " + WindowTasks.ActiveWindow.ToString())

            If WindowTasks.ActiveWindow.CompareTo(WindowTasks(0)) = 0 Then
                WindowTasks(1).Restore()
            Else
                WindowTasks(0).Restore()
            End If
            Return False
        End If

        Me.SuspendLayout()
        TasksBP.Controls.Clear()
        GenerateControls(WindowTasks.Items)
        Me.CenterToScreen()
        Me.ResumeLayout()
        Return True
    End Function



    Private Function getMaxIconSize(ByVal windowItems As List(Of WindowItem)) As Size
        Dim sz As Size
        For Each wi As WindowItem In windowItems
            If wi.Icon.Width > sz.Width Then sz.Width = wi.Icon.Width
            If wi.Icon.Height > sz.Height Then sz.Height = wi.Icon.Height
        Next
        Return sz
    End Function


    Const xOffset As Integer = 3
    Const yOffset As Integer = 7
    Const IconLen As Integer = 32
    Const labelWidth As Integer = 480
    Const labelHeight As Integer = IconLen + 2
    Const NumLabelWidth As Integer = 35

    Dim cLoc As Point
    Dim G As Graphics
    Dim iconSize As New Size(IconLen, IconLen)

    '
    'requires TasksBP is dock fill for height functions to work
    '
    Private Sub GenerateControls(ByVal windowItems As List(Of WindowItem))
        Dim ii, caIdx, thisColumnWidth, thisColumnXOffset As Integer
        Try
            G = Me.CreateGraphics()
            cLoc.Y = yOffset
            cLoc.X = 0
            Dim ctrlArr((windowItems.Count * 3) - 1) As Control
            Me.Height = calculateHeight(windowItems.Count)
            thisColumnXOffset = xOffset

            For ii = 0 To windowItems.Count - 1
                Dim wi As WindowItem = windowItems(ii)

                If cLoc.Y > Me.Height - (iconSize.Height + yOffset) Then
                    cLoc.Y = yOffset
                    thisColumnXOffset += (cLoc.X + thisColumnWidth + xOffset)
                    thisColumnWidth = 0
                End If

                caIdx = ii * 3

                cLoc.X = thisColumnXOffset
                Dim num As Label = createShowTaskNumLabel((ii + 1).ToString)

                ctrlArr(caIdx + 0) = num

                cLoc.X += num.Width
                Dim b As IconImage = createShowTaskIconImage(wi.Icon)
                ctrlArr(caIdx + 1) = b

                cLoc.X += (xOffset + b.Width)
                Dim lbl As Label = createShowTaskLabel(wi.Text)
                ctrlArr(caIdx + 2) = lbl

                thisColumnWidth = Math.Max(thisColumnWidth, lbl.Width)

                cLoc.Y += labelHeight + yOffset

            Next

            TasksBP.Controls.AddRange(ctrlArr)

            Me.Width = cLoc.X + thisColumnWidth + xOffset
            TasksBP.Select()
        Catch ex As Exception
            TS.WError(ex.ToString)
        Finally
            G.Dispose()
        End Try
    End Sub

    Private Function createShowTaskIconImage(ByVal i As Icon) As IconImage
        Dim b As New IconImage
        b.Size = iconSize
        b.Location = cLoc
        b.ImageIcon = i
        Return b
    End Function

    Private Function createShowTaskNumLabel(ByVal t As String) As Label
        Dim num As New Label
        With num
            .Width = NumLabelWidth
            .Height = iconSize.Height
            .BackColor = Color.Transparent
            .TextAlign = System.Drawing.ContentAlignment.MiddleLeft
            .Font = Dispatch.Cfg.NumFont
            .Text = t
            .Location = cLoc
        End With
        Return num
    End Function

    Private Function createShowTaskLabel(ByVal t As String) As Label
        Dim lbl As New Label
        lbl.Location = cLoc
        lbl.Font = Dispatch.Cfg.TextFont
        lbl.Height = labelHeight
        lbl.Width = CInt(G.MeasureString(t, lbl.Font, labelWidth).Width) + xOffset
        lbl.Text = t
        lbl.TextAlign = ContentAlignment.MiddleLeft
        lbl.BackColor = Color.Transparent
        lbl.TextAlign = System.Drawing.ContentAlignment.MiddleLeft
        Return lbl
    End Function

    Private Function calculateHeight(ByVal items As Integer) As Integer
        Dim n As Integer = items
        If items > 10 Then
            n = CInt(Math.Ceiling(items / 2))
        End If
        Return ((labelHeight + yOffset) * n) + yOffset
    End Function


    Protected Overrides Sub DoHide()
        MyBase.DoHide()
        TasksBP.Controls.Clear()
    End Sub

#End Region
End Class

